package com.johnzer.frame.network;


import android.content.Context;
import android.support.annotation.NonNull;

import com.google.gson.GsonBuilder;
import com.johnzer.frame.network.bean.RetrofitParams;
import com.johnzer.frame.network.exception.ServerResultException;
import com.johnzer.frame.network.interfaces.ICodeVerify;
import com.johnzer.frame.network.interfaces.IHttpCallback;
import com.johnzer.frame.network.interfaces.IHttpResult;
import com.johnzer.frame.utils.LogUtils;

import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import io.reactivex.FlowableEmitter;
import io.reactivex.FlowableOnSubscribe;
import io.reactivex.FlowableTransformer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Cancellable;
import io.reactivex.internal.schedulers.IoScheduler;
import io.reactivex.plugins.RxJavaPlugins;
import io.reactivex.schedulers.Schedulers;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Call;
import retrofit2.Converter;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Author   : johnzer
 * Describe : http 管理类
 */
public class HttpManager {

    private Retrofit retrofit;
    private ICodeVerify codeVerify;
    private RetrofitParams params;

    private HttpManager() {
        RxJavaPlugins.setErrorHandler(throwable ->
            LogUtils.e("RxJavaPlugins Error = " + throwable)
        );
//        RxJavaPlugins.getInstance().registerErrorHandler(new RxJavaErrorHandler() {
//            @Override
//            public void handleError(Throwable e) {
//                LogUtils.e("RxJavaPlugins Error = " + e);
//            }
//        });
    }

    public static HttpManager getInstance() {
        return SingletonHolder.instance;
    }

    private static class SingletonHolder {
        static HttpManager instance = new HttpManager();
    }

    public void create(String baseUrl, ICodeVerify codeVerify, RetrofitParams params) {
        Converter.Factory converterFactory = params.getConverterFactory();
//        CallAdapter.Factory callAdapterFactory = params.getCallAdapterFactor();
//        params.setHttps(baseUrl.startsWith("https://"));// 判断是不是https开头的请求
        this.codeVerify = codeVerify;
        this.params = params;
        retrofit = new Retrofit.Builder().baseUrl(baseUrl)
                .addConverterFactory(converterFactory != null ? converterFactory : GsonConverterFactory.create(new GsonBuilder().create()))
//                .addCallAdapterFactory(callAdapterFactory != null ? callAdapterFactory : RxJava2CallAdapterFactory.create())
                .client(createClient(params))
                .build();
    }

    private OkHttpClient createClient(RetrofitParams params) {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();

        // 设置超时
        int connectTimeoutSeconds = params.getConnectTimeoutSeconds();
        if (connectTimeoutSeconds > 0) {
            builder.connectTimeout(connectTimeoutSeconds, TimeUnit.SECONDS);
        }

        int readTimeoutSeconds = params.getReadTimeoutSeconds();
        if (readTimeoutSeconds > 0) {
            builder.readTimeout(readTimeoutSeconds, TimeUnit.SECONDS);
        }

        int writeTimeoutSeconds = params.getWriteTimeoutSeconds();
        if (writeTimeoutSeconds > 0) {
            builder.writeTimeout(writeTimeoutSeconds, TimeUnit.SECONDS);
        }
        // 設置自簽名
        LogUtils.d("isHttps == " + params.isHttps());
        // 这里添加了一个是否需要验证自签名，如果需要将isNeedSSL置为true
        if (params.isHttps() && params.isNeedSSL()){
//            builder.socketFactory(AppInternalUtils.getSocketFactory());
            builder.sslSocketFactory(params.getSslSocketFactory());
        }
        // Log信息拦截器
        if (params.isDebug()) {
            builder.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY));
        }

        ArrayList<Interceptor> interceptors = params.getInterceptors();
        if (interceptors != null && interceptors.size() > 0) {
            for (Interceptor interceptor : interceptors) {
                builder.addInterceptor(interceptor);
            }
        }
        return builder.build();
    }

    public <ApiType> ApiType getApiService(Class<ApiType> type) {
        return retrofit.create(type);
    }

    public <T, Result extends IHttpResult<T>> HttpSubscriber<T> toSubscribe(@NonNull final Call<Result> call, Context context, IHttpCallback<T> listener) {
        return toSubscribe(call, new HttpSubscriber<>(context, listener));
    }

    public <T, Result extends IHttpResult<T>> HttpSubscriber<T> toSubscribe(@NonNull final Call<Result> call, Context context, IHttpCallback<T> listener, boolean isShowToast) {
        return toSubscribe(call, new HttpSubscriber<>(context, listener, isShowToast));
    }

    public <T, Result extends IHttpResult<T>> HttpSubscriber<T> toSubscribe(@NonNull final Call<Result> call, HttpSubscriber<T> callBacks) {
        Disposable disposable = Flowable.create(new FlowableOnSubscribe<Result>() {
            @Override
            public void subscribe(FlowableEmitter<Result> emitter) throws Exception {
                //设置取消监听
                emitter.setCancellable(()-> {
                        LogUtils.e("cancel: ");
                        if (!call.isCanceled()) {
                            call.cancel();
                            callBacks.onCancel();
                        }
                    });
                //同步执行请求，把线程管理交给Rx
                try {
                    callBacks.onStart();
                    Response<Result> response = call.execute();
                    if (!emitter.isCancelled()) {
                        LogUtils.d("onResponse: no cancel");
                        Result result = response.body();// 獲取消息
                        if (result == null) {
                            throw new IllegalStateException("数据为空~");
                        }
                        int code = result.getCode();
                        if (!codeVerify.checkValid(result.getCode())) {
                            throw new ServerResultException(code, codeVerify.formatCodeMessage(code, result.getMsg()));
                        }
                        if (result instanceof HttpResult) {
                            ((HttpResult) result).setHeader(response.headers());
                        }
                        emitter.onNext(result);
                        emitter.onComplete();
                    }
                } catch (Exception exception) {
                    LogUtils.e("exception with: exception = [" + exception.getMessage() + "]");
                    if (!emitter.isCancelled()) {
                        LogUtils.e("onResponse: no cancel");
                        emitter.onError(exception);
                        emitter.onComplete();
                    }
                }
            }
        }, BackpressureStrategy.BUFFER).subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(callBacks.getNext(), callBacks.getError(), callBacks.getOnComplete());

        callBacks.setDisposable(disposable);
//        observableNew.subscribeOn(Schedulers.io())
//                .unsubscribeOn(Schedulers.io())
//                .observeOn(AndroidSchedulers.mainThread())
//                .subscribe(httpSubscriber);
        return callBacks;
    }
    /**
     * 后台线程执行同步，主线程执行异步操作
     * 并且拦截所有错误，不让app崩溃
     *
     * @param <T> 数据类型
     * @return Transformer
     */
    public static <T> FlowableTransformer<T, T> background() {
        return upstream -> upstream.subscribeOn(new IoScheduler())
                        .observeOn(AndroidSchedulers.mainThread())
                        .onErrorResumeNext(Flowable.<T>empty());

    }


    public RetrofitParams getParams() {
        return params;
    }
}
